package com.uwlaser.modules.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.uwlaser.modules.system.domain.SysExternalWebserviceLog;
import com.uwlaser.utils.*;
import com.uwlaser.utils.enums.DictValueEnum;
import com.uwlaser.webservice.exception.WebServiceException;
import lombok.AllArgsConstructor;
import com.uwlaser.base.PageInfo;
import com.uwlaser.base.QueryHelpMybatisPlus;
import com.uwlaser.base.impl.CommonServiceImpl;
import com.uwlaser.modules.system.service.SysExternalWebserviceLogService;
import com.uwlaser.modules.system.service.dto.SysExternalWebserviceLogDto;
import com.uwlaser.modules.system.service.dto.SysExternalWebserviceLogQueryParam;
import com.uwlaser.modules.system.service.mapper.SysExternalWebserviceLogMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import java.util.*;

/**
* @author QZK
* @date 2022-12-07
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = SysExternalWebserviceLogService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysExternalWebserviceLogServiceImpl extends CommonServiceImpl<SysExternalWebserviceLogMapper, SysExternalWebserviceLog> implements SysExternalWebserviceLogService {

    // private final RedisUtils redisUtils;
    private final SysExternalWebserviceLogMapper sysExternalWebserviceLogMapper;

    @Override
    public PageInfo<SysExternalWebserviceLogDto> queryAll(SysExternalWebserviceLogQueryParam query, Pageable pageable) {
        IPage<SysExternalWebserviceLog> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<SysExternalWebserviceLog> page = sysExternalWebserviceLogMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return ConvertUtil.convertPage(page, SysExternalWebserviceLogDto.class);
    }

    @Override
    public List<SysExternalWebserviceLogDto> queryAll(SysExternalWebserviceLogQueryParam query){
        return ConvertUtil.convertList(sysExternalWebserviceLogMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), SysExternalWebserviceLogDto.class);
    }

    @Override
    public SysExternalWebserviceLog getById(Integer id) {
        return sysExternalWebserviceLogMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public SysExternalWebserviceLogDto findById(Integer id) {
        return ConvertUtil.convert(getById(id), SysExternalWebserviceLogDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SysExternalWebserviceLogDto resources) {
        SysExternalWebserviceLog entity = ConvertUtil.convert(resources, SysExternalWebserviceLog.class);
        return sysExternalWebserviceLogMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(SysExternalWebserviceLogDto resources){
        SysExternalWebserviceLog entity = ConvertUtil.convert(resources, SysExternalWebserviceLog.class);
        int ret = sysExternalWebserviceLogMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<Integer> ids){
        // delCaches(ids);
        return sysExternalWebserviceLogMapper.deleteBatchIds(ids);
    }

    /**
     * 添加（不需要事务,保存后异常不回滚）
     * @param log
     * @return
     */
    @Override
    public int addLog(SysExternalWebserviceLog log) {
        return sysExternalWebserviceLogMapper.insert(log);
    }

    @Override
    public int reuploadOne(SysExternalWebserviceLog resources) throws Exception {
        try {
            //请求结果
            JSONObject res = null;

            //方法名称
            String methodName = resources.getMethodName();
            //IP地址
            String url = resources.getUrl();

            if(StringUtils.isEmpty(resources.getHeaderParams())){
                res = MyWebServiceUtil.sendPostRequestWS(url, methodName, resources.getBodyParams());
            } else {
                res = MyWebServiceUtil.sendPostRequestWS(url, methodName, resources.getBodyParams(), resources.getHeaderParams());
            }

            //请求成功,更新状态
            SysExternalWebserviceLog log = new SysExternalWebserviceLog();
            log.setId(resources.getId());
            log.setIsSuccess(DictValueEnum.IS_SUCCESS_Y.getValue());//成功
            log.setRequestResult(JSONObject.toJSONString(res));
            log.setRetriesNum(resources.getRetriesNum() + 1);
            sysExternalWebserviceLogMapper.updateById(log);

        } catch (Exception e) {
            //如果请求失败
            if(e instanceof WebServiceException){
                SysExternalWebserviceLog log = new SysExternalWebserviceLog();
                log.setId(resources.getId());
                log.setRetriesNum(resources.getRetriesNum() + 1);
                log.setErrorMsg(e.getMessage());
                sysExternalWebserviceLogMapper.updateById(log);
            }
            throw e;
        }
        return 0;
    }

    @Override
    public int reuploadAll() {
        //查询失败的请求
        List<SysExternalWebserviceLog> logs = sysExternalWebserviceLogMapper.selectList(new LambdaQueryWrapper<SysExternalWebserviceLog>()
                .eq(SysExternalWebserviceLog::getIsSuccess, DictValueEnum.IS_SUCCESS_N.getValue())
                .orderByAsc(SysExternalWebserviceLog::getId));

        if(logs == null || logs.size() == 0){
            throw new RuntimeException("重传【0】条数据，没有失败的请求可操作重传！");
        }

        //成功数量
        int succeed = 0;
        //失败数量
        int unsuccessful = 0;
        //循环单条上传
        for (SysExternalWebserviceLog log : logs) {
            try {
                reuploadOne(log);
                succeed ++;
            } catch (Exception e) {
                unsuccessful ++;
            }
        }

        if(unsuccessful != 0){
            throw new RuntimeException("重传【"+logs.size()+"】条数据、成功【"+succeed+"】条、失败【"+unsuccessful+"】条！");
        }

        return succeed;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Integer id){
        Set<Integer> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }

    /*
    private void delCaches(Integer id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Integer> ids) {
        for (Integer id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<SysExternalWebserviceLogDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (SysExternalWebserviceLogDto sysExternalWebserviceLog : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("请求地址", sysExternalWebserviceLog.getUrl());
              map.put("方法名称", sysExternalWebserviceLog.getMethodName());
              map.put("请求体参数", sysExternalWebserviceLog.getBodyParams());
              map.put("请求头参数", sysExternalWebserviceLog.getHeaderParams());
              map.put("描述", sysExternalWebserviceLog.getSummarize());
              map.put("错误消息", sysExternalWebserviceLog.getErrorMsg());
              map.put("是否成功", sysExternalWebserviceLog.getIsSuccess());
              map.put("重式次数", sysExternalWebserviceLog.getRetriesNum());
              map.put("返回结果", sysExternalWebserviceLog.getRequestResult());
              map.put("运行耗时", sysExternalWebserviceLog.getElapsedTime());
              map.put("请求时间", sysExternalWebserviceLog.getCreateTime());
              map.put("请求人", sysExternalWebserviceLog.getCreateBy());
              map.put("更新时间", sysExternalWebserviceLog.getUpdateTime());
              map.put("更新人", sysExternalWebserviceLog.getUpdateBy());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/
}
